package com.zbkj.admin.front.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.zbkj.admin.config.CrmebConfig;
import com.zbkj.admin.constants.*;
import com.zbkj.admin.exception.CrmebException;
import com.zbkj.admin.model.cdkey.CardSecret;
import com.zbkj.admin.model.groupbuy.GroupBuyActivitySku;
import com.zbkj.admin.model.groupbuy.GroupBuyRecord;
import com.zbkj.admin.model.groupbuy.GroupBuyUser;
import com.zbkj.admin.model.merchant.Merchant;
import com.zbkj.admin.model.order.*;
import com.zbkj.admin.model.product.Product;
import com.zbkj.admin.model.product.ProductAttrValue;
import com.zbkj.admin.model.product.ProductReply;
import com.zbkj.admin.model.seckill.SeckillProduct;
import com.zbkj.admin.model.user.User;
import com.zbkj.admin.model.user.UserAddress;
import com.zbkj.admin.model.user.UserIntegralRecord;
import com.zbkj.admin.model.wechat.video.PayComponentProduct;
import com.zbkj.admin.model.wechat.video.PayComponentProductSku;
import com.zbkj.admin.page.CommonPage;
import com.zbkj.admin.request.*;
import com.zbkj.admin.response.*;
import com.zbkj.admin.response.groupbuy.GroupBuyActivityRecordForFrontShareUse;
import com.zbkj.admin.result.CommonResultCode;
import com.zbkj.admin.result.OrderResultCode;
import com.zbkj.admin.service.*;
import com.zbkj.admin.util.CrmebUtil;
import com.zbkj.admin.util.RedisUtil;
import com.zbkj.admin.vo.*;
import com.zbkj.admin.front.service.FrontOrderService;
import com.zbkj.admin.front.service.SeckillService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * H5端订单操作
 * +----------------------------------------------------------------------
 * | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2016~2025 https://www.crmeb.com All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
 * +----------------------------------------------------------------------
 * | Author: CRMEB Team <admin@crmeb.com>
 * +----------------------------------------------------------------------
 */
//@Service
@Slf4j
@RequiredArgsConstructor
@SuppressWarnings("all")
public class FrontOrderServiceImplNew implements FrontOrderService, BaseService {

    private final UserService userService;
    private final CartService cartService;
    private final ProductService productService;
    private final ProductAttrValueService productAttrValueService;
    private final OrderService orderService;
    private final UserAddressService userAddressService;
    private final SystemConfigService systemConfigService;
    private final RedisUtil redisUtil;
    private final ShippingTemplatesService shippingTemplatesService;
    private final ShippingTemplatesFreeService shippingTemplatesFreeService;
    private final ShippingTemplatesRegionService shippingTemplatesRegionService;
    private final CouponUserService couponUserService;
    private final CouponProductService couponProductService;
    private final MerchantService merchantService;
    private final TransactionTemplate transactionTemplate;
    private final MerchantOrderService merchantOrderService;
    private final OrderDetailService orderDetailService;
    private final OrderStatusService orderStatusService;
    private final SystemAttachmentService systemAttachmentService;
    private final ProductReplyService productReplyService;
    private final RefundOrderService refundOrderService;
    private final RefundOrderInfoService refundOrderInfoService;
    private final PayComponentProductService payComponentProductService;
    private final PayComponentProductSkuService payComponentProductSkuService;
    private final UserIntegralRecordService userIntegralRecordService;
    private final SystemGroupDataService systemGroupDataService;
    private final SeckillService seckillService;
    private final SeckillProductService seckillProductService;
    private final CouponService couponService;
    private final ProductCategoryService productCategoryService;
    private final RefundOrderStatusService refundOrderStatusService;
    private final CrmebConfig crmebConfig;
    private final CdkeyLibraryService cdkeyLibraryService;
    private final CardSecretService cardSecretService;
    private final SystemFormService systemFormService;
    private final GroupBuyRecordService groupBuyRecordService;
    private final GroupBuyUserService groupBuyUserService;
    private final GroupBuyActivitySkuService groupBuyActivitySkuService;

    /**
     * 预下单V1.7
     *
     * @param request 预下单请求参数
     * @return PreOrderResponse
     */
    @Override
    public OrderNoResponse preOrder_V1_7(PreOrderRequest request) {
        return null;
    }

    /**
     * 加载预下单信息
     *
     * @param preOrderNo 预下单号
     * @return 预下单信息
     */
    @Override
    public PreOrderResponse loadPreOrder(String preOrderNo) {
        return null;
    }

    /**
     * 计算订单价格
     *
     * @param request 计算订单价格请求对象
     * @return ComputedOrderPriceResponse
     */
    @Override
    public ComputedOrderPriceResponse computedOrderPrice(OrderComputedPriceRequest request) {
        // 通过缓存获取预下单对象
        String key = OrderConstants.PRE_ORDER_CACHE_PREFIX + request.getPreOrderNo();
        boolean exists = redisUtil.exists(key);
        Assert.isTrue(!exists, () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "预下单订单不存在"));
        List<OrderMerchantRequest> merchantRequestList = request.getOrderMerchantRequestList();
        merchantRequestList.stream().parallel()
                .filter(m -> m.getShippingType().equals(OrderConstants.ORDER_SHIPPING_TYPE_PICK_UP))
                .peek(m -> {
                    Merchant merchant = merchantService.getByIdException(m.getMerId());
                    Assert.isTrue(!merchant.getIsTakeTheir(), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "请先联系商户管理员开启门店自提"));
                }).toList();

        String orderVoString = redisUtil.get(key).toString();
        PreOrderInfoVo orderInfoVo = JSONObject.parseObject(orderVoString, PreOrderInfoVo.class);
        User user = userService.getInfo();

        return null;
    }

    /**
     * 创建订单
     *
     * @param orderRequest 创建订单请求参数
     * @return OrderNoResponse 订单编号
     */
    @Override
    public OrderNoResponse createOrder(CreateOrderRequest orderRequest) {
        User user = userService.getInfo();
        // 通过缓存获取预下单对象
        String key = OrderConstants.PRE_ORDER_CACHE_PREFIX + orderRequest.getPreOrderNo();
        boolean exists = redisUtil.exists(key);
        Assert.isTrue(!exists, () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "预下单订单不存在"));
        String orderVoString = redisUtil.get(key).toString();
        PreOrderInfoVo orderInfoVo = JSONObject.parseObject(orderVoString, PreOrderInfoVo.class);
        if (orderInfoVo.getType().equals(OrderConstants.ORDER_TYPE_SECKILL)) {
            return seckillService.createOrder(orderRequest, orderInfoVo, user);
        }
        // 拼团商品单独处理
        if (orderInfoVo.getType().equals(OrderConstants.ORDER_TYPE_PITUAN)) {
            return groupBuyRecordService.createOrder(orderRequest, orderInfoVo, user, key);
        }
        UserAddress userAddress = null;
        List<OrderMerchantRequest> orderMerchantRequestList = orderRequest.getOrderMerchantRequestList();
        if (orderInfoVo.getSecondType().equals(OrderConstants.ORDER_SECOND_TYPE_CLOUD)
                || orderInfoVo.getSecondType().equals(OrderConstants.ORDER_SECOND_TYPE_CDKEY)
                || orderInfoVo.getSecondType().equals(OrderConstants.ORDER_SECOND_TYPE_VIRTUALLY)) {
            orderRequest.setAddressId(0);
        } else {
            if (orderMerchantRequestList.stream().anyMatch(e -> e.getShippingType().equals(OrderConstants.ORDER_SHIPPING_TYPE_EXPRESS))) {
                Assert.isTrue(ObjectUtil.isNull(orderRequest.getAddressId()), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "请选择收货地址"));
                userAddress = userAddressService.getById(orderRequest.getAddressId());
                Assert.isTrue(ObjectUtil.isNull(userAddress) || userAddress.getIsDel(), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "收货地址有误"));
            }
            if (orderMerchantRequestList.stream().anyMatch(e -> e.getShippingType().equals(OrderConstants.ORDER_SHIPPING_TYPE_EXPRESS))) {
                Assert.isTrue(ObjectUtil.isNull(orderRequest.getAddressId()), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "请选择收货地址"));
                userAddress = userAddressService.getById(orderRequest.getAddressId());
                Assert.isTrue(ObjectUtil.isNull(userAddress) || userAddress.getIsDel(), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "收货地址有误"));
            }
            if (orderMerchantRequestList.stream().anyMatch(e -> e.getShippingType().equals(OrderConstants.ORDER_SHIPPING_TYPE_PICK_UP))) {
                orderMerchantRequestList.forEach(m -> {
                    if (m.getShippingType().equals(OrderConstants.ORDER_SHIPPING_TYPE_PICK_UP)) {
                        Merchant merchant = merchantService.getByIdException(m.getMerId());
                        Assert.isTrue(!merchant.getIsTakeTheir(), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, StrUtil.format("{}没有配置店铺地址，请联系客服", merchant.getName())));
                    }
                });
            }
        }
        return null;
    }

    /**
     * 用户积分记录——订单抵扣
     *
     * @param uid         用户ID
     * @param useIntegral 使用的积分
     * @param integral    用户当前积分
     * @param orderNo     订单号
     * @return 用户积分记录
     */
    private UserIntegralRecord initOrderUseIntegral(Integer uid, Integer useIntegral, Integer integral, String orderNo, String title) {
//        StrUtil.format("订单使用{}积分进行金额抵扣", useIntegral)
//        StrUtil.format("积分订单使用{}积分进行兑换", useIntegral)
        return new UserIntegralRecord().setUid(uid).setLinkId(orderNo).setLinkType(IntegralRecordConstants.INTEGRAL_RECORD_LINK_TYPE_ORDER)
                .setType(IntegralRecordConstants.INTEGRAL_RECORD_TYPE_SUB).setIntegral(useIntegral)
                .setBalance(integral - useIntegral).setTitle(title)
                .setStatus(IntegralRecordConstants.INTEGRAL_RECORD_STATUS_COMPLETE);
    }

    /**
     * 退款单退回商品
     */
    @Override
    public Boolean returningGoods(OrderRefundReturningGoodsRequest request) {
        RefundOrder refundOrder = refundOrderService.getByRefundOrderNo(request.getRefundOrderNo());
        Assert.isTrue(ObjectUtil.isNull(refundOrder), () -> new CrmebException(OrderResultCode.REFUND_ORDER_NOT_EXIST));
        Assert.isTrue(refundOrder.getRefundStatus() != 4, () -> new CrmebException(OrderResultCode.REFUND_ORDER_STATUS_ABNORMAL));

        if (refundOrder.getReturnGoodsType() == 1) {
            Assert.isTrue(StrUtil.isBlank(request.getExpressName()), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "请选择快递公司"));
            Assert.isTrue(StrUtil.isBlank(request.getTrackingNumber()), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "请填写运单号"));
            refundOrder.setExpressName(request.getExpressName()).setTrackingNumber(request.getTrackingNumber());
        }
        refundOrder.setTelephone(request.getTelephone()).setRefundStatus(5);

        return transaction(() -> {
            refundOrderService.updateById(refundOrder);
            refundOrderStatusService.add(refundOrder.getRefundOrderNo(), RefundOrderConstants.REFUND_ORDER_LOG_RETURNING_GOODS, "售后单用户退回商品");
            return Boolean.TRUE;
        });
    }

    /**
     * 撤销退款单
     *
     * @param refundOrderNo 退款单号
     */
    @Override
    public Boolean revoke(String refundOrderNo) {
        return refundOrderService.revoke(refundOrderNo);
    }

    /**
     * 订单列表(v1.4.0)
     *
     * @param request 搜索参数
     * @return PageInfo
     */
    @Override
    public PageInfo<OrderFrontDataResponse> list_v1_4(OrderFrontListRequest request) {
        Integer userId = userService.getUserIdException();

        PageInfo<Order> pageInfo = orderService.getUserOrderList_v1_4(userId, request);
        List<Order> orderList = pageInfo.getList();
        if (CollUtil.isEmpty(orderList)) {
            return CommonPage.copyPageInfo(pageInfo, CollUtil.newArrayList());
        }
        List<Integer> merIdList = orderList.stream().map(Order::getMerId).filter(i -> i > 0).distinct().collect(Collectors.toList());
        Map<Integer, Merchant> merchantMap = null;
        if (CollUtil.isNotEmpty(merIdList)) {
            merchantMap = merchantService.getMerIdMapByIdList(merIdList);
        }
        List<OrderFrontDataResponse> responseList = CollUtil.newArrayList();
        DateTime cancelTime;
        for (Order order : orderList) {
            OrderFrontDataResponse infoResponse = new OrderFrontDataResponse();
            BeanUtils.copyProperties(order, infoResponse);
            // 订单详情对象列表
            List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
            List<OrderInfoFrontDataResponse> infoResponseList = CollUtil.newArrayList();
            orderDetailList.forEach(e -> {
                OrderInfoFrontDataResponse orderInfoResponse = new OrderInfoFrontDataResponse();
                BeanUtils.copyProperties(e, orderInfoResponse);
                infoResponseList.add(orderInfoResponse);
            });
            infoResponse.setOrderInfoList(infoResponseList);
            if (order.getMerId() > 0) {
                infoResponse.setMerName(merchantMap.get(order.getMerId()).getName());
            }
            if (!order.getPaid()) {
                cancelTime = DateUtil.offset(order.getCreateTime(), DateField.MINUTE, crmebConfig.getOrderCancelTime());
                infoResponse.setCancelTime(cancelTime.getTime());
            }
            // 在次添加拼团订单信息
            if (order.getType().equals(OrderConstants.ORDER_TYPE_PITUAN)) {
                GroupBuyUser currentGroupBuyUser = groupBuyUserService.getByOrderNo(order.getOrderNo());
                if (ObjectUtil.isNotNull(currentGroupBuyUser) && currentGroupBuyUser.getId() > 0) {
                    GroupBuyRecord currentGroupBuyRecord = groupBuyRecordService.getById(currentGroupBuyUser.getGroupRecordId());
                    GroupBuyActivitySku currentSku = null;
                    GroupBuyActivityRecordForFrontShareUse groupBuyActivityRecord = new GroupBuyActivityRecordForFrontShareUse();
                    if (ObjectUtil.isNotNull(currentGroupBuyRecord)) {
                        currentSku = groupBuyActivitySkuService.getByAttrId(currentGroupBuyUser.getGroupActivityId(), currentGroupBuyRecord.getSkuid());
                        groupBuyActivityRecord.setBuyingCountNum(currentGroupBuyRecord.getBuyingCountNum());
                        groupBuyActivityRecord.setYetBuyingNum(currentGroupBuyRecord.getYetBuyingNum());
                    }
                    if (ObjectUtil.isNull(currentSku)) { //这里有可能在购买后，管理端删除基础商品的sku后，关联操作拼团sku后导致这里查询不到，拼团价为null的情况下 前端不予生成拼团码
                        groupBuyActivityRecord.setActivePrice(null);
                    } else {
                        groupBuyActivityRecord.setActivePrice(currentSku.getActivePrice());
                    }
                    groupBuyActivityRecord.setGroupActivityId(currentGroupBuyUser.getGroupActivityId());
                    groupBuyActivityRecord.setProductId(currentGroupBuyUser.getProductGroupId());
                    groupBuyActivityRecord.setGroupRecordId(currentGroupBuyUser.getGroupRecordId());
                    groupBuyActivityRecord.setGroupLeaderNickname(currentGroupBuyUser.getGroupNickname());
                    groupBuyActivityRecord.setGroupLeaderAvatar(currentGroupBuyUser.getGroupAvatar());
                    groupBuyActivityRecord.setGroupLeaderUid(currentGroupBuyUser.getGroupUid());
                    infoResponse.setGroupBuyActivityRecord(groupBuyActivityRecord);
                }
            }
            responseList.add(infoResponse);
        }

        return CommonPage.copyPageInfo(pageInfo, responseList);
    }

    /**
     * 移动端订单详情
     *
     * @param orderNo 订单编号
     * @return OrderFrontDetailResponse
     */
    @Override
    public OrderFrontDetailResponse frontDetail(String orderNo) {
        User currentUser = userService.getInfo();
        Order order = orderService.getByOrderNo(orderNo);
        if (order.getIsUserDel() || order.getIsMerchantDel() || !order.getUid().equals(currentUser.getId())) {
            throw new CrmebException(OrderResultCode.ORDER_NOT_EXIST);
        }
        OrderFrontDetailResponse response = new OrderFrontDetailResponse();
        BeanUtils.copyProperties(order, response);
        List<MerchantOrder> merchantOrderList = merchantOrderService.getByOrderNo(orderNo);
        List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(orderNo);
        for (OrderDetail orderDetail : orderDetailList) { // set 拼团活动号
            response.setGroupBuyActivityId(orderDetail.getGroupBuyActivityId());
        }
        Map<Integer, List<OrderDetail>> orderDetailMap = orderDetailList.stream().collect(Collectors.groupingBy(OrderDetail::getMerId));

        List<MerchantOrderFrontDetailResponse> merDetailResponseList = CollUtil.newArrayList();
        for (MerchantOrder merchantOrder : merchantOrderList) {
            MerchantOrderFrontDetailResponse merDetailResponse = new MerchantOrderFrontDetailResponse();
            BeanUtils.copyProperties(merchantOrder, merDetailResponse);
            if (!merchantOrder.getSecondType().equals(OrderConstants.ORDER_SECOND_TYPE_INTEGRAL)) {
                Merchant merchant = merchantService.getById(merchantOrder.getMerId());
                merDetailResponse.setMerName(merchant.getName());
                if (merchantOrder.getShippingType().equals(OrderConstants.ORDER_SHIPPING_TYPE_PICK_UP)) {
                    merDetailResponse.setMerPhone(merchant.getPhone());
                    merDetailResponse.setMerProvince(merchant.getProvince());
                    merDetailResponse.setMerCity(merchant.getCity());
                    merDetailResponse.setMerDistrict(merchant.getDistrict());
                    merDetailResponse.setMerAddressDetail(merchant.getAddressDetail());
                    merDetailResponse.setMerLatitude(merchant.getLatitude());
                    merDetailResponse.setMerLongitude(merchant.getLongitude());
                }
                merDetailResponse.setIsSelf(merchant.getIsSelf());
            }
            List<OrderDetail> detailList = orderDetailMap.get(merchantOrder.getMerId());
            List<OrderInfoFrontDataResponse> dataResponseList = detailList.stream().map(d -> {
                OrderInfoFrontDataResponse dataResponse = new OrderInfoFrontDataResponse();
                BeanUtils.copyProperties(d, dataResponse);
                if (order.getSecondType().equals(OrderConstants.ORDER_SECOND_TYPE_CLOUD) || order.getSecondType().equals(OrderConstants.ORDER_SECOND_TYPE_CDKEY)) {
                    if (order.getStatus() <= 3 || order.getStatus() == 9) {
                        dataResponse.setExpand("");
                        dataResponse.setCardSecretIds("");
                    } else if (order.getSecondType().equals(OrderConstants.ORDER_SECOND_TYPE_CDKEY)) {
                        String cardSecretIds = d.getCardSecretIds();
                        List<Integer> cardSecretIdList = CrmebUtil.stringToArray(cardSecretIds);
                        List<CardSecret> cardSecretList = cardSecretService.findByIds(cardSecretIdList);
                        dataResponse.setCardSecretList(cardSecretList);
                    }
                }
                return dataResponse;
            }).collect(Collectors.toList());
            merDetailResponse.setOrderInfoList(dataResponseList);
            merDetailResponseList.add(merDetailResponse);
        }
        response.setMerchantOrderList(merDetailResponseList);
        if (!order.getPaid()) {
            DateTime cancelTime = DateUtil.offset(order.getCreateTime(), DateField.MINUTE, crmebConfig.getOrderCancelTime());
            response.setCancelTime(cancelTime.getTime());
        }
        return response;
    }

    /**
     * 订单商品评论列表
     *
     * @param pageRequest 分页参数
     * @return PageInfo
     */
    @Override
    public PageInfo<InfoReplyResponse> replyList(PageParamRequest pageRequest) {
        Integer userId = userService.getUserIdException();
        PageInfo<OrderDetail> pageInfo = orderDetailService.getReplyList(userId, false, pageRequest);
        List<OrderDetail> orderDetailList = pageInfo.getList();
        if (CollUtil.isEmpty(orderDetailList)) {
            return CommonPage.copyPageInfo(pageInfo, CollUtil.newArrayList());
        }
        List<Integer> merIdList = orderDetailList.stream().map(OrderDetail::getMerId).distinct().collect(Collectors.toList());
        Map<Integer, Merchant> merchantMap = merchantService.getMerIdMapByIdList(merIdList);
        List<InfoReplyResponse> responseList = orderDetailList.stream().map(info -> {
            InfoReplyResponse replyResponse = new InfoReplyResponse();
            BeanUtils.copyProperties(info, replyResponse);
            replyResponse.setMerName(merchantMap.get(info.getMerId()).getName());
            replyResponse.setMerIsSelf(merchantMap.get(info.getMerId()).getIsSelf());
            return replyResponse;
        }).collect(Collectors.toList());
        return CommonPage.copyPageInfo(pageInfo, responseList);
    }

    /**
     * 评价订单商品
     *
     * @param request 评价参数
     */
    @Override
    public Boolean replyProduct(OrderProductReplyRequest request) {
        Order order = orderService.getByOrderNo(request.getOrderNo());
        if (!(order.getStatus().equals(OrderConstants.ORDER_STATUS_COMPLETE) || order.getStatus().equals(OrderConstants.ORDER_STATUS_TAKE_DELIVERY))) {
            throw new CrmebException(OrderResultCode.ORDER_STATUS_ABNORMAL, "订单状态异常，无法评价");
        }
        OrderDetail orderDetail = orderDetailService.getById(request.getOrderDetailId());
        if (ObjectUtil.isNull(orderDetail) || !order.getOrderNo().equals(orderDetail.getOrderNo())) {
            throw new CrmebException(OrderResultCode.ORDER_DETAIL_NOT_EXIST);
        }
        if (!orderDetail.getIsReceipt()) {
            throw new CrmebException(OrderResultCode.ORDER_DETAIL_RECEIPT, "请收货后再评论");
        }
        if (orderDetail.getIsReply()) {
            throw new CrmebException(OrderResultCode.ORDER_DETAIL_REPLY);
        }
        orderDetail.setIsReply(true);
        User user = userService.getInfo();
        ProductReply productReply = new ProductReply();
        BeanUtils.copyProperties(request, productReply);
        productReply.setMerId(orderDetail.getMerId());
        productReply.setProductId(orderDetail.getProductId());
        if (order.getType().equals(OrderConstants.ORDER_TYPE_SECKILL)) {
            SeckillProduct seckillProduct = seckillProductService.getById(orderDetail.getProductId());
            productReply.setProductId(seckillProduct.getProductId());
        }
        productReply.setAttrValueId(orderDetail.getAttrValueId());
        productReply.setSku(orderDetail.getSku());
        productReply.setUid(user.getId());
        productReply.setNickname(user.getNickname());
        String cdnUrl = systemAttachmentService.getCdnUrl();
        productReply.setAvatar(systemAttachmentService.clearPrefix(user.getAvatar(), cdnUrl));
        if (CollUtil.isNotEmpty(request.getPics())) {
            List<String> pics = request.getPics().stream().map(e -> systemAttachmentService.clearPrefix(e, cdnUrl)).collect(Collectors.toList());
            productReply.setPics(String.join(",", pics));
        }
        Boolean execute = transactionTemplate.execute(e -> {
            orderDetailService.updateById(orderDetail);
            productReplyService.save(productReply);
            return Boolean.TRUE;
        });
        if (!execute) {
            throw new CrmebException("评价订单商品失败");
        }
        return execute;
    }

    /**
     * 取消订单
     *
     * @param orderNo 订单编号
     */
    @Override
    public Boolean cancel(String orderNo,String reason) {
        Integer uid = userService.getUserIdException();
        Order order = orderService.getByOrderNo(orderNo);
        if (!order.getUid().equals(uid)) {
            throw new CrmebException(OrderResultCode.ORDER_NOT_EXIST);
        }
        if (order.getPaid()) {
            throw new CrmebException(OrderResultCode.ORDER_PAID);
        }
        Boolean cancel = orderService.cancel(orderNo, true);
        if (cancel) {
            redisUtil.lPush(TaskConstants.ORDER_TASK_REDIS_KEY_AFTER_CANCEL_BY_USER, order.getOrderNo());
        }
        // 处理拼团的取消订单逻辑
        if (order.getType().equals(OrderConstants.ORDER_TYPE_PITUAN)) {
            List<OrderDetail> ods = orderDetailService.getByOrderNo(order.getOrderNo());
            for (OrderDetail od : ods) {
                GroupBuyActivitySku groupBuyActivitySku = groupBuyActivitySkuService.getByAttrId(od.getGroupBuyActivityId(), od.getAttrValueId());
                groupBuyActivitySkuService.rollBackSKUStock(order, groupBuyActivitySku.getGroupActivityId(), od.getAttrValueId(), od.getPayNum());
            }

        }
        return cancel;
    }

    /**
     * 订单收货
     *
     * @param orderNo 订单号
     * @return Boolean
     */
    @Override
    public Boolean takeDelivery(String orderNo) {
        Integer userId = userService.getUserIdException();
        Order order = orderService.getByOrderNo(orderNo);
        if (!order.getUid().equals(userId)) {
            throw new CrmebException(OrderResultCode.ORDER_NOT_EXIST);
        }
        if (!order.getCancelStatus().equals(OrderConstants.ORDER_CANCEL_STATUS_NORMAL)) {
            throw new CrmebException(OrderResultCode.ORDER_CANCEL);
        }
        if (order.getRefundStatus().equals(OrderConstants.ORDER_REFUND_STATUS_ALL)) {
            throw new CrmebException(OrderResultCode.ORDER_STATUS_ABNORMAL, "已退款订单无法收货");
        }
        if (!order.getStatus().equals(OrderConstants.ORDER_STATUS_WAIT_RECEIPT)) {
            throw new CrmebException(OrderResultCode.ORDER_STATUS_ABNORMAL);
        }
        if (order.getRefundStatus().equals(OrderConstants.ORDER_REFUND_STATUS_APPLY)) {
            throw new CrmebException(OrderResultCode.ORDER_STATUS_ABNORMAL, "请先撤销售后，再进行收货操作");
        }
        Boolean execute = transactionTemplate.execute(e -> {
            orderService.takeDelivery(orderNo);
            orderDetailService.takeDelivery(orderNo);
            orderStatusService.createLog(order.getOrderNo(), OrderStatusConstants.ORDER_STATUS_USER_TAKE_DELIVERY, OrderStatusConstants.ORDER_LOG_USER_RECEIPT);
            return Boolean.TRUE;
        });
        if (execute) {
            //后续操作放入redis
            redisUtil.lPush(TaskConstants.ORDER_TASK_REDIS_KEY_AFTER_TAKE_BY_USER, orderNo);
        }
        return execute;
    }

    /**
     * 删除订单
     *
     * @param orderNo 订单号
     * @return Boolean
     */
    @Override
    public Boolean delete(String orderNo) {
        Integer userId = userService.getUserIdException();
        Order order = orderService.getByOrderNo(orderNo);
        if (!order.getUid().equals(userId)) {
            throw new CrmebException(OrderResultCode.ORDER_NOT_EXIST);
        }
        if (!(order.getStatus().equals(OrderConstants.ORDER_STATUS_COMPLETE) || order.getStatus().equals(OrderConstants.ORDER_STATUS_CANCEL))) {
            throw new CrmebException(OrderResultCode.ORDER_STATUS_ABNORMAL, "未完成订单无法删除");
        }
        if (order.getIsUserDel()) {
            throw new CrmebException(OrderResultCode.ORDER_DELETE);
        }
        order.setIsUserDel(true);
        return transactionTemplate.execute(e -> {
            orderService.updateById(order);
            orderStatusService.createLog(orderNo, OrderStatusConstants.ORDER_STATUS_USER_DELETE, OrderStatusConstants.ORDER_LOG_USER_DELETE);
            return Boolean.TRUE;
        });
    }

    /**
     * 售后申请列表(可申请售后列表)
     *
     * @param request 搜索参数
     */
    @Override
    public PageInfo<OrderDetail> getAfterSaleApplyList(CommonSearchRequest request) {
        Integer uid = userService.getUserIdException();
        PageInfo<OrderDetail> pageInfo = orderDetailService.findAfterSaleApplyList(uid, request);
        List<OrderDetail> orderDetailList = pageInfo.getList();
        if (CollUtil.isEmpty(orderDetailList)) {
            return pageInfo;
        }
        List<Integer> merIdList = orderDetailList.stream().map(OrderDetail::getMerId).distinct().collect(Collectors.toList());
        Map<Integer, Merchant> merchantMap = merchantService.getMapByIdList(merIdList);
        orderDetailList.forEach(o -> {
            o.setMerName(merchantMap.get(o.getMerId()).getName());
        });
        return pageInfo;
    }

    /**
     * 查询退款理由
     *
     * @return 退款理由集合
     */
    @Override
    public List<String> getRefundReason() {
        String reasonString = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_KEY_STOR_REASON);
        reasonString = CrmebUtil.UnicodeToCN(reasonString);
        reasonString = reasonString.replace("rn", "n");
        return Arrays.asList(reasonString.split("\\n"));
    }

    /**
     * 订单退款申请
     *
     * @param request 申请参数
     * @return Boolean
     */
    @Override
    public Boolean refundApply(OrderRefundApplyRequest request) {
        Integer uid = userService.getUserIdException();
        Order order = orderService.getByOrderNo(request.getOrderNo());
        if (!order.getUid().equals(uid) || order.getIsUserDel()) {
            throw new CrmebException(OrderResultCode.ORDER_NOT_EXIST);
        }
        if (order.getCancelStatus() > OrderConstants.ORDER_CANCEL_STATUS_NORMAL) {
            throw new CrmebException(OrderResultCode.ORDER_CANCEL);
        }
        if (!order.getPaid()) {
            throw new CrmebException(OrderResultCode.ORDER_NOT_PAID);
        }
        if (order.getRefundStatus().equals(OrderConstants.ORDER_REFUND_STATUS_ALL)) {
            throw new CrmebException(OrderResultCode.ORDER_REFUND_ED);
        }
        if (order.getStatus().equals(OrderConstants.ORDER_STATUS_COMPLETE)) {
            throw new CrmebException(OrderResultCode.ORDER_STATUS_ABNORMAL, "已完成订单无法申请退款");
        }
        if (!order.getGroupBuyRecordStatus().equals(99)) {
            // 拼团判断
            if (!order.getGroupBuyRecordStatus().equals(10)) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "拼团状态异常，无法申请退款");
            }
        }
        OrderDetail orderDetail = orderDetailService.getById(request.getOrderDetailId());
        if (ObjectUtil.isNull(orderDetail) || !orderDetail.getOrderNo().equals(order.getOrderNo())) {
            throw new CrmebException(OrderResultCode.ORDER_DETAIL_NOT_EXIST);
        }
        int canApplyNum = orderDetail.getPayNum() - orderDetail.getApplyRefundNum() - orderDetail.getRefundNum();
        if (canApplyNum < request.getNum()) {
            throw new CrmebException(CommonResultCode.VALIDATE_FAILED, StrUtil.format("剩余可退款数量为{}", canApplyNum));
        }
        MerchantOrder merchantOrder = merchantOrderService.getOneByOrderNo(order.getOrderNo());

        RefundOrder refundOrder = new RefundOrder();
        refundOrder.setRefundOrderNo(CrmebUtil.getOrderNo(OrderConstants.ORDER_PREFIX_REFUND));
        refundOrder.setOrderNo(order.getOrderNo());
        refundOrder.setMerId(order.getMerId());
        refundOrder.setUid(order.getUid());
        refundOrder.setRealName(merchantOrder.getRealName());
        refundOrder.setUserPhone(merchantOrder.getUserPhone());
        refundOrder.setUserAddress(merchantOrder.getUserAddress());
        refundOrder.setRefundPrice(order.getPayPrice());
        refundOrder.setTotalNum(request.getNum());
        refundOrder.setRefundReasonWap(request.getText());
        refundOrder.setRefundReasonWapImg(systemAttachmentService.clearPrefix(request.getReasonImage()));
        refundOrder.setRefundReasonWapExplain(request.getExplain());
        refundOrder.setRefundStatus(OrderConstants.MERCHANT_REFUND_ORDER_STATUS_APPLY);
        refundOrder.setRefundPlatCouponPrice(merchantOrder.getPlatCouponPrice());
        refundOrder.setAfterSalesType(request.getAfterSalesType());
        refundOrder.setReturnGoodsType(request.getReturnGoodsType());

        RefundOrderInfo refundOrderInfo = new RefundOrderInfo();
        refundOrderInfo.setRefundOrderNo(refundOrder.getRefundOrderNo());
        refundOrderInfo.setMerId(orderDetail.getMerId());
        refundOrderInfo.setOrderDetailId(orderDetail.getId());
        refundOrderInfo.setProductId(orderDetail.getProductId());
        refundOrderInfo.setProductName(orderDetail.getProductName());
        refundOrderInfo.setImage(orderDetail.getImage());
        refundOrderInfo.setAttrValueId(orderDetail.getAttrValueId());
        refundOrderInfo.setSku(orderDetail.getSku());
        refundOrderInfo.setPrice(orderDetail.getPrice());
        refundOrderInfo.setPayNum(orderDetail.getPayNum());
        refundOrderInfo.setProductType(orderDetail.getProductType());
        refundOrderInfo.setPayPrice(orderDetail.getPayPrice());
        refundOrderInfo.setApplyRefundNum(request.getNum());
        // 临时性计算退款金额、积分
        if (request.getNum().equals(orderDetail.getPayNum())) {
            refundOrderInfo.setRefundPrice(orderDetail.getPayPrice());
            refundOrderInfo.setRefundUseIntegral(orderDetail.getUseIntegral());
            refundOrderInfo.setRefundGainIntegral(orderDetail.getGainIntegral());
            refundOrderInfo.setRefundFreightFee(orderDetail.getFreightFee());
        } else {
            refundOrderInfo.setRefundUseIntegral(0);
            refundOrderInfo.setRefundGainIntegral(0);
            BigDecimal ratio = new BigDecimal(request.getNum().toString()).divide(new BigDecimal(orderDetail.getPayNum().toString()), 10, RoundingMode.HALF_UP);
            refundOrderInfo.setRefundPrice(orderDetail.getPayPrice().multiply(ratio).setScale(2, RoundingMode.HALF_UP));
            if (orderDetail.getUseIntegral() > 0) {
                refundOrderInfo.setRefundUseIntegral(new BigDecimal(orderDetail.getUseIntegral().toString()).multiply(ratio).setScale(0, RoundingMode.HALF_UP).intValue());
            }
            if (orderDetail.getGainIntegral() > 0) {
                refundOrderInfo.setRefundGainIntegral(new BigDecimal(orderDetail.getGainIntegral().toString()).multiply(ratio).setScale(0, RoundingMode.HALF_UP).intValue());
            }
            if (orderDetail.getPlatCouponPrice().compareTo(BigDecimal.ZERO) > 0) {
                refundOrderInfo.setRefundPlatCouponPrice(orderDetail.getPlatCouponPrice().multiply(ratio).setScale(2, RoundingMode.HALF_UP));
            }
            refundOrderInfo.setRefundFreightFee(orderDetail.getFreightFee().multiply(ratio).setScale(2, RoundingMode.HALF_UP));
        }

        refundOrder.setRefundPrice(refundOrderInfo.getRefundPrice());
        refundOrder.setRefundUseIntegral(refundOrderInfo.getRefundUseIntegral());
        refundOrder.setRefundGainIntegral(refundOrderInfo.getRefundGainIntegral());
        refundOrder.setRefundPlatCouponPrice(refundOrderInfo.getRefundPlatCouponPrice());
        refundOrder.setRefundFreightFee(refundOrderInfo.getRefundFreightFee());

        order.setRefundStatus(OrderConstants.ORDER_REFUND_STATUS_APPLY);
        orderDetail.setApplyRefundNum(orderDetail.getApplyRefundNum() + request.getNum());

        String outRefundNo = CrmebUtil.getOrderNo(OrderConstants.ORDER_PREFIX_REFUND);
        refundOrder.setOutRefundNo(outRefundNo);
        Boolean execute = transactionTemplate.execute(e -> {
            orderService.updateById(order);
            orderDetailService.updateById(orderDetail);
            refundOrderService.save(refundOrder);
            refundOrderInfoService.save(refundOrderInfo);
            refundOrderStatusService.add(refundOrder.getRefundOrderNo(), RefundOrderConstants.REFUND_ORDER_LOG_APPLY, "用户发起退款单申请");
            return Boolean.TRUE;
        });
        if (Boolean.FALSE.equals(execute)) throw new CrmebException("申请退款失败");
        return execute;
    }

    /**
     * 退款订单列表
     *
     * @param request 搜索参数
     * @return PageInfo
     */
    @Override
    public PageInfo<RefundOrderResponse> getRefundOrderList(OrderAfterSalesSearchRequest request) {
        return refundOrderService.getH5List(request);
    }

    /**
     * 退款订单详情
     *
     * @param refundOrderNo 退款订单号
     * @return RefundOrderInfoResponse
     */
    @Override
    public RefundOrderInfoResponse refundOrderDetail(String refundOrderNo) {
        return refundOrderService.getRefundOrderDetailByRefundOrderNo(refundOrderNo);
    }

    /**
     * 订单物流详情
     */
    @Override
    public LogisticsResultVo getLogisticsInfo(Integer invoiceId) {
        return orderService.getLogisticsInfo(invoiceId);
    }

    /**
     * 获取发货单列表
     *
     * @param orderNo 订单号
     * @return 发货单列表
     */
    @Override
    public OrderInvoiceFrontResponse getInvoiceList(String orderNo) {
        Order order = orderService.getByOrderNo(orderNo);
        List<OrderInvoiceResponse> invoiceList = orderService.getInvoiceList(orderNo);
        OrderInvoiceFrontResponse response = new OrderInvoiceFrontResponse();
        response.setInvoiceList(invoiceList);
        if (CollUtil.isEmpty(invoiceList)) {
            response.setNum(1);
            response.setDeliveryNum(0);
            return response;
        }
        response.setNum(order.getStatus().equals(OrderConstants.ORDER_STATUS_PART_SHIPPING) ? invoiceList.size() + 1 : invoiceList.size());
        response.setDeliveryNum(invoiceList.size());
        return response;
    }

    /**
     * 获取个人中心订单数量
     */
    @Override
    public OrderCenterNumResponse userCenterNum() {
        Integer userId = userService.getUserIdException();
        OrderCenterNumResponse response = new OrderCenterNumResponse();
        response.setAwaitPayCount(orderService.getCountByStatusAndUid(OrderConstants.ORDER_STATUS_WAIT_PAY, userId));
        response.setAwaitShippedCount(orderService.getCountByStatusAndUid(OrderConstants.ORDER_STATUS_WAIT_SHIPPING, userId));
        response.setReceiptCount(orderService.getCountByStatusAndUid(OrderConstants.ORDER_STATUS_WAIT_RECEIPT, userId));
        response.setVerificationCount(orderService.getCountByStatusAndUid(OrderConstants.ORDER_STATUS_AWAIT_VERIFICATION, userId));
        response.setAwaitReplyCount(orderDetailService.getAwaitReplyCount(userId)).setRefundCount(refundOrderService.getRefundingCount(userId));
        return response;
    }

    /**
     * 获取订单状态图
     */
    @Override
    public List<HashMap<String, Object>> getOrderStatusImage() {
        List<HashMap<String, Object>> mapList = systemGroupDataService.getListMapByGid(GroupDataConstants.GROUP_DATA_ID_ORDER_STATUS_IMAGE);
        return mapList;
    }

    private List<MyRecord> validateProductStock(PreOrderInfoVo orderInfoVo) {
        List<MyRecord> recordList = CollUtil.newArrayList();
        if (orderInfoVo.getSecondType().equals(OrderConstants.ORDER_SECOND_TYPE_VIDEO)) {// 视频号订单
            // 查询商品信息 视频号都是单品下单
            List<PreOrderInfoDetailVo> detailVos = orderInfoVo.getMerchantOrderVoList().get(0).getOrderInfoList();
            PayComponentProduct product = payComponentProductService.getById(detailVos.get(0).getProductId());
            if (ObjectUtil.isNull(product)) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "商品信息不存在，请刷新后重新选择");
            }
            if (product.getIsDel()) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "商品已删除，请刷新后重新选择");
            }
            if (!product.getStatus().equals(5)) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "商品已下架，请刷新后重新选择");
            }
            if (product.getStock().equals(0) || product.getStock() < detailVos.get(0).getPayNum()) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "商品库存不足，请刷新后重新选择");
            }
            // 查询商品规格属性值信息
            ProductAttrValue attrValue = productAttrValueService.getByIdAndProductIdAndType(detailVos.get(0).getAttrValueId(), detailVos.get(0).getProductId(), ProductConstants.PRODUCT_TYPE_COMPONENT);
            if (ObjectUtil.isNull(attrValue)) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "商品规格信息不存在，请刷新后重新选择");
            }
            if (attrValue.getStock().equals(0) || attrValue.getStock() < detailVos.get(0).getPayNum()) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "商品规格库存不足，请刷新后重新选择");
            }
            // 查询视频商品规格属性值
            PayComponentProductSku productSku = payComponentProductSkuService.getByProIdAndAttrValueId(product.getId(), attrValue.getId());
            if (ObjectUtil.isNull(productSku)) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "商品sku信息不存在，请刷新后重新选择");
            }
            if (productSku.getStockNum().equals(0) || productSku.getStockNum() < detailVos.get(0).getPayNum()) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "商品sku库存不足，请刷新后重新选择");
            }

            MyRecord record = new MyRecord();
            record.set("productId", product.getId()).set("attrValueId", detailVos.getFirst().getAttrValueId());
            record.set("attrValueVersion", attrValue.getVersion()).set("num", detailVos.getFirst().getPayNum());
            record.set("skuId", productSku.getId()).set("skuVersion", productSku.getVersion());
            recordList.add(record);
            return recordList;
        }
        if (orderInfoVo.getSecondType().equals(OrderConstants.ORDER_SECOND_TYPE_INTEGRAL)) {
            List<PreOrderInfoDetailVo> orderInfoList = orderInfoVo.getMerchantOrderVoList().getFirst().getOrderInfoList();
            orderInfoList.forEach(info -> {
                // 查询商品信息
                Product product = productService.getById(info.getProductId());
                Assert.isTrue(ObjectUtil.isNull(product) || product.getIsDel(),
                        () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品信息不存在"));
                Assert.isTrue(!product.getIsShow(), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品信息不存在"));
                Assert.isTrue(product.getStock().equals(0) || info.getPayNum() > product.getStock(),
                        () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品库存不足"));
                // 查询商品规格属性值信息
                ProductAttrValue attrValue = productAttrValueService.getByIdAndProductIdAndType(
                        info.getAttrValueId(), info.getProductId(), product.getType(), product.getMarketingType());

                Assert.isTrue(ObjectUtil.isNull(attrValue),
                        () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品规格信息不存在"));

                if (ObjectUtil.isNull(attrValue)) {
                    throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品规格信息不存在");
                }
                if (!attrValue.getIsShow()) {
                    throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品规格信息无效");
                }
                if (attrValue.getStock() < info.getPayNum()) {
                    throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品库存不足");
                }
                User user = userService.getInfo();
                if (user.getIntegral() < (attrValue.getRedeemIntegral() * info.getPayNum())) {
                    throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "用户积分不足");
                }
                if (product.getExchangeNum() > 0) {
                    Integer orderProductNum = orderService.getProductNumCount(user.getId(), product.getId(), product.getMarketingType());
                    if (product.getExchangeNum() < (info.getPayNum() + orderProductNum)) {
                        throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "积分商品购买已达限量");
                    }
                }

                MyRecord record = new MyRecord();
                record.set("productId", info.getProductId()).set("num", info.getPayNum());
                record.set("attrValueId", info.getAttrValueId()).set("attrValueVersion", attrValue.getVersion());
                record.set("type", attrValue.getType()).set("marketingType", attrValue.getMarketingType());
                if (product.getType().equals(ProductConstants.PRODUCT_TYPE_CLOUD)) {
                    record.set("expand", attrValue.getExpand());
                }
                if (product.getType().equals(ProductConstants.PRODUCT_TYPE_CDKEY)) {
                    record.set("cdkeyId", attrValue.getCdkeyId());
                }
                record.set("isPaidMember", product.getIsPaidMember()).set("vipPrice", attrValue.getVipPrice());
                recordList.add(record);
            });
            return recordList;
        }
        // 普通商品
        List<PreMerchantOrderVo> merchantOrderVoList = orderInfoVo.getMerchantOrderVoList();
        merchantOrderVoList.forEach(merchantOrderVo -> {
            Merchant merchant = merchantService.getByIdException(merchantOrderVo.getMerId());
            Assert.isTrue(!merchant.getIsSwitch(), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "商户已关闭，请重新下单"));
            merchantOrderVo.getOrderInfoList().forEach(info -> {
                // 查询商品信息
                Product product = productService.getById(info.getProductId());
                Assert.isTrue(ObjectUtil.isNull(product) || product.getIsDel(),
                        () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品信息不存在"));
                Assert.isTrue(!product.getIsShow(), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品已下架"));
                Assert.isTrue(product.getStock().equals(0) || info.getPayNum() > product.getStock(),
                        () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品库存不足"));

                // 查询商品规格属性值信息
                ProductAttrValue attrValue = productAttrValueService.getByIdAndProductIdAndType(
                        info.getAttrValueId(), info.getProductId(), product.getType(), product.getMarketingType());
                Assert.isTrue(ObjectUtil.isNull(attrValue), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品规格信息不存在"));
                Assert.isTrue(!attrValue.getIsShow(), () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品规格信息无效"));
                Assert.isTrue(attrValue.getStock() < info.getPayNum(),
                        () -> new CrmebException(CommonResultCode.VALIDATE_FAILED, "购买的商品库存不足"));

                MyRecord record = new MyRecord().set("productId", info.getProductId()).set("num", info.getPayNum());
                record.set("attrValueId", info.getAttrValueId()).set("attrValueVersion", attrValue.getVersion());
                record.set("type", attrValue.getType()).set("marketingType", attrValue.getMarketingType());
                if (product.getType().equals(ProductConstants.PRODUCT_TYPE_CLOUD)) {
                    record.set("expand", attrValue.getExpand());
                }
                if (product.getType().equals(ProductConstants.PRODUCT_TYPE_CDKEY)) {
                    record.set("cdkeyId", attrValue.getCdkeyId());
                }
                record.set("isPaidMember", product.getIsPaidMember()).set("vipPrice", attrValue.getVipPrice());
                recordList.add(record);
            });
        });
        return recordList;
    }

    /**
     * 计算订单运费
     */
    @Override
    public void getFreightFee_V_1_8(PreOrderInfoVo orderInfoVo, UserAddress userAddress, Boolean userIsPaidMember) {
        BigDecimal freightFee = BigDecimal.ZERO;

    }

}
